#ifndef LUA_PARAMETERS_BUILDING
#define LUA_PARAMETERS_BUILDING
#include <luaParameters/config.h>
#include <luaState/luaState.h>
#include <vector>
#include <string>
#include <list>
#include <complex>
#include <mutex>
#include <boost/filesystem.hpp>
#include <boost/function.hpp>
#include <sol/table.hpp>

#include <boost/archive/basic_archive.hpp>
#include <boost/serialization/version.hpp>     // 确保首先包含此文件
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/array_wrapper.hpp>
#include <boost/serialization/utility.hpp>
#include <boost/serialization/list.hpp>        // list.hpp 应在 version.hpp 之后
#include <boost/serialization/complex.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/assume_abstract.hpp>

#include <appendix/point.h>

namespace lua{
struct luaState;
};
namespace lua{
	class
	LUA_PARAMETERS_EXPORT_API
	luaParameters{
		friend class boost::serialization::access;
		template<class Archive>
		void save(Archive & ar, const unsigned int version) const
		{
			std::map<std::string, std::string> sets;
			//parametersSweepSettings(sets);
			ar & getList() & m_sweepSettings;
		}
		template<class Archive>
		void load(Archive & ar, const unsigned int version)
		{
			//std::map<std::string, std::string> sets;
			std::vector< std::vector<std::string> > res;
			ar & res & m_sweepSettings;
			add_variable(res);
			//setParametersSweepSettings(sets);

		}
		BOOST_SERIALIZATION_SPLIT_MEMBER()
	public:
		luaParameters();
		luaParameters(const luaParameters&);
		luaParameters(std::shared_ptr<lua::luaState>);
		void setState(std::shared_ptr<lua::luaState>);
		std::shared_ptr<lua::luaState> state(){ return _state;};
		virtual ~luaParameters(){};
		bool initState();
		void setGlobalState(std::shared_ptr<lua::luaState>);
		bool initGlobalState();
		bool parametersSweepSettings(std::map<std::string, std::string>& settings) const;
		bool setParametersSweepSettings(const std::map<std::string, std::string>& settings);
		sol::table parametersSweepModule(){return m_parameterSweepModule;};

	public:
		std::vector< std::vector<std::string> > getList() const;
		bool setList(const std::vector< std::vector<std::string> >&);
		bool set_variable(const std::string&, const std::string&);
		bool set_variable(const std::string& key , const std::string& val, const std::string& des);
		bool add_variable(const std::string&, const std::string&);
		bool add_variable(const std::string& key , const std::string& val, const std::string& des);
		bool add_variable(const std::string& key , const std::string& val,const std::string& des,const std::string& val_impl);
		bool add_variable( const std::vector< std::vector<std::string> > & );
		bool remove_variable(const std::string&);
		bool remove_all();
		bool change_variable_expression(const std::string&,const std::string&);
		bool change_variable_name(const std::string&,const std::string& );
		bool check_variable_name(const std::string&);
		bool swap_variables_index(const std::string&,const std::string&);
		bool change_variable_description(const std::string&,const std::string& );
		bool change_variable_sweep_values(const std::string&,const std::string& );
		bool change_variable_sweep_state(const std::string&,const std::string& );
		bool change_variable_sweep_state(const std::string&,bool );
		bool get_variable_sweep_state(const std::string& );

		bool init_sweep_list();
		bool sweep_list(std::vector<std::string>& names, std::vector< std::vector<double> >& values);
		bool sweep_index(std::vector< std::vector<int> >& values);

		bool update_sweep_list_to_variables(int);

		bool check_expression(const std::string&);
		bool evaluate(const std::string& expr,double&);
		bool evaluate(const std::string& expr,std::string&);
		bool parse();
	protected:
		std::shared_ptr<lua::luaState> _state;  //local state
		sol::table m_module;
		bool m_bNeedUpdate;

		std::shared_ptr<lua::luaState> _globalState;  //global state
		sol::table m_parameterSweepModule;
		std::map<std::string,std::string> m_sweepSettings;
	};
	class
	LUA_PARAMETERS_EXPORT_API
	luaExpression{
		friend class boost::serialization::access;
		template<class Archive>
			void serialize(Archive & ar, const unsigned int ver)
		{
			ar  & m_parameters & m_bNeedEvaluate & m_bValid & m_bSynatexError;
		}
	protected:
		std::shared_ptr<lua::luaParameters> m_parameters;
		mutable bool m_bNeedEvaluate;
		mutable bool m_bValid;
		mutable bool m_bSynatexError;
	public:
		luaExpression();
		virtual void set_parameters(std::shared_ptr<lua::luaParameters> p);
		double to_double();
		virtual void build() const;
		virtual bool valid() const { return m_bValid; }
		virtual bool need_evaluate() const { return m_bNeedEvaluate; }
		virtual bool synatex_error() const { return m_bSynatexError; }
	};
	class
	LUA_PARAMETERS_EXPORT_API
	luaDoubleExpression
	:public luaExpression{
		friend class boost::serialization::access;
		template<class Archive>
			void serialize(Archive & ar, const unsigned int ver)
		{
			ar & boost::serialization::base_object<luaExpression>(*this);
			ar & m_expr & m_value;
		}
	protected:
		std::string m_expr;
		mutable double m_value;
	public:
		luaDoubleExpression();
		luaDoubleExpression(double);
		luaDoubleExpression(const std::string& expr);
		virtual void set_parameters(std::shared_ptr<lua::luaParameters> p) override;

		void set_expression(const std::string& expr);
		void set_expression(double);
		virtual void set_expression_impl(const std::string& expr);
		const std::string& expression() const { return m_expr; }

		virtual void build() const override;
		double operator()(void) const;
		double operator()(bool&) const;
		bool valuate(double&) const;
		bool operator==(const luaDoubleExpression& ) const;
		bool operator!=(const luaDoubleExpression& ) const;
	};

	class
	LUA_PARAMETERS_EXPORT_API
	luaPoint3DdExpression
	:public luaExpression{
		friend class boost::serialization::access;
		template<class Archive>
			void serialize(Archive & ar, const unsigned int ver)
		{
			ar & boost::serialization::base_object<luaExpression>(*this);
			ar & m_value & m_exprs;
		}
	protected:
		std::array<luaDoubleExpression,3> m_exprs;
		mutable Point3Dd m_value;
	public:
		luaPoint3DdExpression();
		luaPoint3DdExpression(const std::string&,const std::string&,const std::string&);
		luaPoint3DdExpression(double,double,double);
		virtual void set_parameters(std::shared_ptr<lua::luaParameters> p) override;

		void set_expression(const std::string&,const std::string&,const std::string&);
		void set_expression(double,double,double);
		void set_expression(const luaDoubleExpression&, int);
		void set_expression(double, int);
		void set_expression(const luaDoubleExpression&, const luaDoubleExpression&, const luaDoubleExpression&);

		const std::array<luaDoubleExpression,3>& expression() const{ return m_exprs; }
		virtual void build() const;
		void build_impl(int) const;
		Point3Dd operator()(void) const;
		Point3Dd operator()(bool&) const;
		bool valuate(Point3Dd&) const;
		bool valuate(std::array<double,3>&) const;
		bool valuate(std::vector<double>&) const;
		bool operator==(const luaPoint3DdExpression& ) const;
		bool operator!=(const luaPoint3DdExpression& ) const;
	private:
		void set_valid() const;
		void set_need_evaluate() const;
		void set_expression_impl(const std::string& expr,int idx);
		void set_synatex_error() const;
	};

	class
	LUA_PARAMETERS_EXPORT_API
	luaPoint2DdExpression
	:public luaExpression{

		friend class boost::serialization::access;
		template<class Archive>
			void serialize(Archive & ar, const unsigned int ver)
		{
			ar & boost::serialization::base_object<luaExpression>(*this);
			ar & m_value & m_exprs;
		}
	protected:
		std::array<luaDoubleExpression,2> m_exprs;
		mutable Point2Dd m_value;
	public:
		luaPoint2DdExpression();
		luaPoint2DdExpression(const std::string&,const std::string&);
		virtual void set_parameters(std::shared_ptr<lua::luaParameters> p) override;

		void set_expression(const std::string&,const std::string&);
		void set_expression(double,double);
		void set_expression(const luaDoubleExpression&, int);
		void set_expression(const luaDoubleExpression&, const luaDoubleExpression&);

		const std::array<luaDoubleExpression,2>& expression() const{ return m_exprs; }
		virtual void build() const;
		void build_impl(int) const;
		Point2Dd operator()(void) const;
		Point2Dd operator()(bool&) const;
		bool valuate(Point2Dd&) const;
		bool operator==(const luaPoint2DdExpression& ) const;
		bool operator!=(const luaPoint2DdExpression& ) const;
	private:
		void set_valid() const;
		void set_need_evaluate() const;
		void set_expression_impl(const std::string& expr,int idx);
		void set_synatex_error() const;
	};
};

#endif
